package org.holynite.TiebarSpiderFx.Main

import configuration.ApplicationContextConfiguration
import javafx.fxml.FXMLLoader
import javafx.scene.Parent
import javafx.scene.Scene
import javafx.stage.Stage
import javafx.util.Callback
import org.springframework.context.ApplicationContext
import org.springframework.core.io.ClassPathResource
import utils.LogFactory

import java.util.logging.Logger

/**
 * Created by midnite on 14/11/27.
 */
class SPFxmlLoader {
	static final ApplicationContext ctx = ApplicationContextConfiguration.getAppContext()
	static final Logger log = LogFactory.getLogger(SPFxmlLoader)
	private static final Boolean NEVER_BIND_EVENTS = false

	private void bindEvents(Stage stage, AbstractController controller) {
		controller.parentStage = stage
		stage.onShowing = controller.onShowing()
		stage.onShown = controller.onShown()
		stage.onHiding = controller.onHiding()
		stage.onHidden = controller.onHidden()
		stage.onCloseRequest = controller.onClose()
	}

	def LoadParent(String url, Stage stage = null) throws FxmlLoadException {
		def fxmlStream = new ClassPathResource(url).inputStream
		try {
			FXMLLoader loader = new FXMLLoader()
			loader.setControllerFactory([
			        "call": { Class<? extends AbstractController> aClass -> ctx.getBean(aClass)}
			] as Callback<Class<?>, Object>)
			def parent = loader.load(fxmlStream) as Parent
			if (stage && !NEVER_BIND_EVENTS) {
				def controller = loader.controller as AbstractController
				controller.parentStage = stage
				bindEvents(stage, controller)
			}
			parent
		} catch (ioe) {
			log.throwing("SPFxmlLoader", "Load", ioe)
			throw new FxmlLoadException(404, "File does not exists or unreachable.")
			null
		} finally {
			fxmlStream.close()
		}
	}

	def LoadScene(String url, String style, Stage stage = null) throws FxmlLoadException {
		try {
			def root = LoadParent(url, stage)
			def scene = new Scene(root)
			scene.stylesheets.add(style)
			if (stage) {
				stage.scene = scene
				stage.sizeToScene()
			}
			scene
		} catch (e) {
			switch (e) {
				case NullPointerException:
					throw new FxmlLoadException(404, "Null value found.")
					break
				case FxmlLoadException:
					throw e
					break
			}
			null
		}
	}

	def LoadScene(String url, String style, Double width, Double height, Stage stage = null) throws FxmlLoadException {
		try {
			def root = LoadParent(url, stage)
			def scene = new Scene(root, width, height)
			scene.stylesheets.add(style)
			if (stage) {
				stage.scene = scene
				stage.sizeToScene()
			}
			scene
		} catch (e) {
			switch (e) {
				case NullPointerException:
					throw new FxmlLoadException(404, "Null value found.")
				break
				case FxmlLoadException:
					throw e
				break
			}
			null
		}
	}

	static class FxmlLoadException extends Exception {
		int exceptionCode

		FxmlLoadException(int code, String message) {
			super(message)
			exceptionCode = code
		}
	}
}
